home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus Extra 1997 #1
/
Amiga Plus Extra 1997 #1.iso
/
programme
/
tools
/
leoutils
/
scrdump.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-25
|
11KB
|
418 lines
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <libraries/asl.h>
#include <libraries/iff.h> /* The great IFF library */
#include <exec/exec.h>
#include <graphics/displayinfo.h>
#include <intuition/intuitionbase.h>
#if defined __SASC
#include <proto/intuition.h>
#include <proto/asl.h>
#include <proto/dos.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#else
#include <clib/intuition_protos.h>
#include <clib/asl_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/exec_protos.h>
#endif
#define VERSION "1.1"
/***********************************************\
* *
* ILBM basic definitions *
* *
\***********************************************/
/* ILBM compression techniques */
#define cmpNone 0
#define cmpByteRun1 1
/* ILBM masking techniques */
#define mskNone 0
#define mskHasMask 1
#define mskHasTransparentColor 2
#define mskLasso 3
/***********************************************\
* *
* Needed for iff.library *
* *
\***********************************************/
/* A macro */
#define MAXPACKEDSIZE(s) ((s)*2)
/* how many bytes to buffer in BODY chunk */
#define BODYBUFSIZE 10000
/***********************************************\
* *
* Constants and variables *
* *
\***********************************************/
static char *Ver = "$VER:ScrDump " VERSION " " __AMIGADATE__ " ©1995-6 Leopold-Soft";
typedef enum SAVEMODE {
SM_WIN,
SM_SCR
};
typedef enum ERRORCODE {
EC_NONE,
EC_NO_ACTIVE_WIN,
EC_OLD_OR_NO_IFF_LIBRARY,
EC_OLD_OS,
EC_CANT_SAVE
};
#define SF_NOWINBORDERS (1<<0)
#define SF_SAFE (1<<1)
static char *defaultFileName = "RAM:ScrDumpFile";
/***********************************************\
* *
* SaveScrWin saves a window or screen to the *
* given file. *
* *
\***********************************************/
static int SaveScrWin(struct Screen *scr, struct Window *win, char *name, ULONG flags) {
extern struct IntuitionBase *IntuitionBase;
extern struct ExecBase *SysBase;
struct Library *IFFBase;
IFFL_HANDLE iffH;
BOOL success = FALSE;
UBYTE *bodyBuf = NULL;
struct IFFL_BMHD bmhd;
UBYTE *oneLine = NULL;
enum SAVEMODE mode = scr ? SM_SCR : SM_WIN;
BOOL OS3 = SysBase->LibNode.lib_Version >= 39;
struct RastPort *srcRPort;
struct DisplayInfo myDisplayInfo;
UBYTE *colors = NULL;
BOOL quickSave = (!OS3 || (mode == SM_SCR &&
GetBitMapAttr(scr->RastPort.BitMap, BMA_FLAGS)
& BMF_STANDARD));
LONG depth, xStart=0, yStart=0, width, height;
int i;
ULONG modeID, iffrowbytes;
struct RastPort stdLineRPort1, stdLineRPort2, scrLineRPort;
struct BitMap *stdLineBMap1=NULL, *stdLineBMap2=NULL, *scrLineBMap=NULL;
char vStr[80];
time_t tt;
struct tm *t;
if (!OS3 && mode == SM_WIN)
return EC_OLD_OS;
if (!(IFFBase = OpenLibrary(IFFNAME, 21L)))
return EC_OLD_OR_NO_IFF_LIBRARY;
if (name == NULL || name[0] == '\0')
name = defaultFileName;
if (mode == SM_WIN) {
scr = win->WScreen;
srcRPort = win->RPort;
} else {
srcRPort = &scr->RastPort;
}
modeID = GetVPModeID(&scr->ViewPort);
if (OS3) {
depth = GetBitMapAttr(srcRPort->BitMap, BMA_DEPTH);
} else {
depth = srcRPort->BitMap->Depth;
}
if (mode == SM_WIN) {
if (flags && SF_NOWINBORDERS) {
xStart = win->BorderLeft;
yStart = win->BorderTop;
width = win->Width - xStart - win->BorderRight;
height = win->Height - yStart - win->BorderBottom;
} else {
width = win->Width;
height = win->Height;
}
} else {
width = scr->Width;
height = scr->Height;
}
iffrowbytes = ((width + 15L) & ~15L) >> 3;
GetDisplayInfoData(NULL, (UBYTE *) &myDisplayInfo, sizeof(struct DisplayInfo),
DTAG_DISP, modeID);
if (!(colors = malloc((1<<depth) * 3)) ||
!(bodyBuf = malloc(BODYBUFSIZE)))
goto error;
if (!quickSave) {
if (!(stdLineBMap1 = AllocBitMap(width+16, 1, depth, BMF_MINPLANES, NULL)) ||
!(stdLineBMap2 = AllocBitMap(width+16, 1, depth, BMF_MINPLANES, NULL)) ||
!(scrLineBMap = AllocBitMap(scr->Width, 1, depth, BMF_MINPLANES, srcRPort->BitMap)) ||
!(oneLine = malloc((iffrowbytes<<3) + 16)))
goto error;
InitRastPort(&stdLineRPort1);
stdLineRPort1.BitMap = stdLineBMap1;
InitRastPort(&stdLineRPort2);
stdLineRPort2.BitMap = stdLineBMap2;
scrLineRPort = *srcRPort;
scrLineRPort.Layer = NULL;
scrLineRPort.BitMap = scrLineBMap;
}
iffH = IFFL_OpenIFF(name, IFFL_MODE_WRITE);
if (iffH) {
/*
Let's write the BMHD chunk
*/
bmhd.w = width;
bmhd.h = height;
bmhd.x = xStart;
bmhd.y = yStart;
bmhd.nPlanes = depth;
bmhd.masking = mskNone;
bmhd.compression = cmpByteRun1;
bmhd.pad1 = 0;
bmhd.transparentColor = 0;
bmhd.xAspect = myDisplayInfo.Resolution.y;
bmhd.yAspect = myDisplayInfo.Resolution.x;
bmhd.pageWidth = bmhd.w;
bmhd.pageHeight = bmhd.h;
success = IFFL_PushChunk(iffH, ID_ILBM, ID_BMHD);
if (success) success = IFFL_WriteChunkBytes(iffH, &bmhd, sizeof(bmhd));
if (success) success = IFFL_PopChunk(iffH);
/*
Let's write the CMAP chunk
*/
if (success) success = IFFL_PushChunk(iffH, ID_ILBM, ID_CMAP);
for (i=0; i<(1<<depth); i++) {
ULONG tmpCol[3];
if (OS3) {
GetRGB32(scr->ViewPort.ColorMap, (ULONG)i, 1, tmpCol);
colors[i*3+0] = tmpCol[0] >> 24;
colors[i*3+1] = tmpCol[1] >> 24;
colors[i*3+2] = tmpCol[2] >> 24;
} else {
tmpCol[0] = GetRGB4(scr->ViewPort.ColorMap, (ULONG)i);
colors[i*3+0] = ((tmpCol[0] ) >> 8) * 0x11;
colors[i*3+1] = ((tmpCol[0] & 0x0F0 ) >> 4) * 0x11;
colors[i*3+2] = ((tmpCol[0] & 0x00F ) ) * 0x11;
}
}
if (success) success = IFFL_WriteChunkBytes(iffH, colors, (LONG)(1<<depth)*3);
if (success) success = IFFL_PopChunk(iffH);
/*
Let's write a CAMG chunk
*/
if (success) success = IFFL_PushChunk(iffH, ID_ILBM, ID_CAMG);
if (success) success = IFFL_WriteChunkBytes(iffH, &modeID, sizeof(modeID));
if (success) success = IFFL_PopChunk(iffH);
/*
Let's write an ANNO chunk
*/
time(&tt);
t = localtime(&tt);
strcpy(vStr, "$VER: Written by ScrDump " VERSION " (");
i = strlen(vStr);
t->tm_mon++;
vStr[i++] = '0' + t->tm_mday/10;
vStr[i++] = '0' + t->tm_mday%10;
vStr[i++] = '.';
vStr[i++] = '0' + t->tm_mon/10;
vStr[i++] = '0' + t->tm_mon%10;
vStr[i++] = '.';
vStr[i++] = '0' + (t->tm_year%100)/10;
vStr[i++] = '0' + t->tm_year%10;
strcpy(vStr + i, ") ©1995-6 Leopold-Soft");
/* sprintf(vStr, "%02d.%02d.%02d) ©1995-6 Leopold-Soft",
t->tm_mday, t->tm_mon, t->tm_year % 100);
*/
if (success) success = IFFL_PushChunk(iffH, ID_ILBM, ID_ANNO);
if (success) success = IFFL_WriteChunkBytes(iffH, vStr, strlen(vStr)+1);
if (success) success = IFFL_PopChunk(iffH);
/*
Let's write a BODY chunk
*/
if (success) {
int row, iplane, bodysize=0;
int rowOffset = -srcRPort->BitMap->BytesPerRow;
success = IFFL_PushChunk(iffH, ID_ILBM, ID_BODY);
for (row=0; row < bmhd.h; ++row) {
if (!quickSave) {
int i;
ReadPixelLine8( srcRPort, xStart, row+yStart, width, oneLine, &scrLineRPort);
for (i=0; i<16; i++)
oneLine[width+i] = 0;
WritePixelLine8(&stdLineRPort1, 0, 0, width+16, oneLine, &stdLineRPort2);
} else {
rowOffset += srcRPort->BitMap->BytesPerRow;
}
for (iplane=0; iplane < depth; ++iplane) {
int comprsize;
/* Flush buffer if full */
if (bodysize > (BODYBUFSIZE-MAXPACKEDSIZE(iffrowbytes))) {
if (success) {
success = IFFL_WriteChunkBytes(iffH, bodyBuf, bodysize);
bodysize = 0;
}
}
/* Compress one row */
if (success) {
if (!quickSave) {
success = comprsize = IFFL_CompressBlock(
stdLineRPort1.BitMap->Planes[iplane],
bodyBuf+bodysize, iffrowbytes, IFFL_COMPR_BYTERUN1);
} else {
success = comprsize = IFFL_CompressBlock(
srcRPort->BitMap->Planes[iplane] + rowOffset,
bodyBuf+bodysize, iffrowbytes, IFFL_COMPR_BYTERUN1);
}
bodysize += comprsize;
}
}
}
/* Flush the rest of body */
if (bodysize && success)
success = IFFL_WriteChunkBytes(iffH, bodyBuf, bodysize);
if (success) success = IFFL_PopChunk(iffH);
}
IFFL_CloseIFF(iffH);
}
error:
if (oneLine) free(oneLine);
if (scrLineBMap) FreeBitMap(scrLineBMap);
if (stdLineBMap2) FreeBitMap(stdLineBMap2);
if (stdLineBMap1) FreeBitMap(stdLineBMap1);
if (bodyBuf) free(bodyBuf);
if (colors) free(colors);
CloseLibrary(IFFBase);
return success ? EC_NONE : EC_CANT_SAVE;
}
static int SaveScreen(struct Screen *scr, char *name, ULONG flags) {
return SaveScrWin(scr, NULL, name, flags);
}
static int SaveWindow(struct Window *win, char *name, ULONG flags) {
return SaveScrWin(NULL, win, name, flags);
}
/***********************************************\
* *
* The main program *
* *
\***********************************************/
int main(int argc, char **argv) {
int errorcode = EXIT_SUCCESS;
int i;
enum SAVEMODE savemode = SM_SCR;
ULONG flags = 0;
char *fileName = defaultFileName;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-w")) {
savemode = SM_WIN;
} else if (!strcmp(argv[i], "-s")) {
savemode = SM_SCR;
} else if (!strcmp(argv[i], "-b")) {
flags |= SF_NOWINBORDERS;
} else if (!strcmp(argv[i], "-B")) {
flags &= ~SF_NOWINBORDERS;
} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "?")) {
Printf("\nScreen Dump v" VERSION " ©1995-6 Leopold-Soft\n"
"Usage: %s [-w] [-s] [-b] [-B] [-h|?] [filnam]\n"
"-w\tSave active window (requires OS3)\n"
"-s\tSave uppermost screen (default)\n"
"-b\tDon't save window borders\n"
"-B\tSave window borders (default)\n"
"-h|?\tShow this help\n"
"filnam\tSpecify file name to save to (default: %s)\n\n"
, argv[0], defaultFileName);
return EXIT_SUCCESS;
} else {
fileName = argv[i];
}
}
Delay(500);
switch(savemode) {
case SM_SCR:
errorcode = SaveScreen(IntuitionBase->FirstScreen, fileName, flags);
DisplayBeep(IntuitionBase->FirstScreen);
break;
case SM_WIN:
if (!IntuitionBase->ActiveWindow) {
errorcode = EC_NO_ACTIVE_WIN;
} else {
errorcode = SaveWindow(IntuitionBase->ActiveWindow, fileName, flags);
DisplayBeep(IntuitionBase->ActiveWindow->WScreen);
}
break;
}
switch (errorcode) {
case EC_NONE:
Printf("%s: Saved to \"%s\", ok!\n", argv[0], fileName);
break;
case EC_NO_ACTIVE_WIN:
Printf("%s: Error: no active window!\n", argv[0]);
errorcode = EXIT_FAILURE;
break;
case EC_OLD_OR_NO_IFF_LIBRARY:
Printf("%s: Error: iff.library v21 or newer required!\n", argv[0]);
errorcode = EXIT_FAILURE;
break;
case EC_OLD_OS:
Printf("%s: Error: Can't save windows under OS2.x!\n", argv[0]);
errorcode = EXIT_FAILURE;
break;
default:
Printf("%s: Error: can't save to \"%s\"!\n", argv[0], fileName);
errorcode = EXIT_FAILURE;
break;
}
return errorcode;
}